#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <syslog.h>
#include <sys/types.h>

/* 1.open an unused pseudotermios, save the pts's name to 'save_name'
 * 2.set this pseudotermios as raw input and output mode
 * if successful return the pasudotermios's file descripter,else -1 */
int open_pty(char *save_name,int name_len)
{

    int fd;
    struct termios t;
    
    fd=posix_openpt(O_RDWR | O_NOCTTY | O_NONBLOCK);
    if(fd==-1) return -1;

    grantpt(fd);
    unlockpt(fd);
    strncpy(save_name,ptsname(fd),name_len);

    if(tcgetattr(fd,&t)==-1) {
        close(fd);
        return -1;
    }

    t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO );
    t.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR |
                    INPCK | ISTRIP | IXON | PARMRK);
    t.c_oflag &= ~OPOST; /* Disable all output processing */

    t.c_cc[VMIN]=0; /* character-at-a-time input */
    t.c_cc[VTIME]=0; /* without blocking */
    if(tcsetattr(fd,TCSAFLUSH,&t)==-1){
        close(fd);
        return -1;
    }
    return fd;
}

int daemonize(void)
{
    if(fork()) exit(EXIT_SUCCESS); /* parent terminates */
    setsid(); /* become leader of new session */

    if(fork()) exit(EXIT_SUCCESS); /* i don't want be a session leader */
    umask(0);
    chdir("/");
    
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    return 0;
}

int main(int argc,char *argv[])
{
    int fd,num;
    char name[24];
    char buf[256];

    daemonize();
    setlogmask(LOG_UPTO(LOG_NOTICE));
    openlog(argv[0],LOG_CONS | LOG_PID |LOG_NDELAY, LOG_LOCAL1);

    fd=open_pty(name,sizeof(name));
    if(fd<0) goto err;
    else syslog(LOG_NOTICE,"open pty %s,fd is: %d",name,fd);

    write(fd,"Hello world!\n",13);
    sleep(60);
    syslog(LOG_NOTICE,"60 seconds passed,try read data");
    
    num=read(fd,buf,sizeof(buf));
    buf[num]='\0';
    syslog(LOG_NOTICE,"got %d bytes data",num);
    if(num>0) syslog(LOG_NOTICE,"%s",buf);

err:
    close(fd);
    return 0;
    
}

/* A linux pseudo termios example: create a pseudo termios at /dev/pts/n,
 * Other programe can communicate with our by using /dev/pts/n. Both we and
 * others programe can access(read/write) this pseudo termios.
 *
 * Compile: gcc pseudotermios.c -o pseudotermios
 * Run: ./pseudotermios
 * Get pseudo termios name from syslog: cat /var/log/syslog | grep pseudotermios
 * like this: ==>Jul  4 16:07:04 dell ./pseudotermios[8206]: open pty /dev/pts/0
 *
 * Other programe(like cat) can read the string we writts to termios:
 * cat /dev/pts/n
 * ==> Hello world
 *
 * Also they can sent data by using this pseudo termios to me:
 * echo "hello world" > /dev/pts/n
 * 
 * After 60 seconds passed, we can find this string in syslog:
 * cat /var/log/syslog | grep pseudotermios
 * ==> 
 * Jul  4 16:07:04 dell ./pseudotermios[8206]: open pty /dev/pts/0
 * Jul  4 16:08:04 dell ./pseudotermios[8206]: 60 seconds passed,try read data
 * Jul  4 16:08:04 dell ./pseudotermios[8206]: got 12 bytes data
 * Jul  4 16:08:04 dell ./pseudotermios[8206]: hello world
 */

